#include json.ahk
#include XInput.ahk
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
Process, Priority, , High
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

; Increase the following value to make the mouse cursor move faster:
JoyMultiplier = 0.90

; Decrease the following value to require less joystick displacement-from-center
; to start moving the mouse.  However, you may need to calibrate your joystick
; -- ensuring it's properly centered -- to avoid cursor drift. A perfectly tight
; and centered joystick could use a value of 1:
JoyThreshold = 20

; Change the following to true to invert the Y-axis, which causes the mouse to
; move vertically in the direction opposite the stick:
InvertYAxis := false

; If your system has more than one joystick, increase this value to use a joystick
; other than the first:
JoystickNumber = 1

JoystickPrefix = %JoystickNumber%Joy

; ~ Config:
SetKeyDelay -1 

#SingleInstance

JoyThresholdUpper := 50 + JoyThreshold
JoyThresholdLower := 50 - JoyThreshold

if InvertYAxis
    YAxisMultiplier = -1
else
    YAxisMultiplier = 1

; Minimum to be considered "pressed", between 1 (0.39%) and 255 (100%).
ThresholdLower = 63
ThresholdUpper = 200

; Simple button to key maps

ButtonA  = 1
ButtonB  = 2
ButtonX  = 3
ButtonY  = 4
ButtonLb = 5
ButtonRb = 6
ButtonBk = 7
ButtonSt = 8
ButtonLs = 9
ButtonRs = 10

Hotkey, %JoystickPrefix%%ButtonA%, ButtonA
Hotkey, %JoystickPrefix%%ButtonB%, ButtonB
Hotkey, %JoystickPrefix%%ButtonX%, ButtonX
Hotkey, %JoystickPrefix%%ButtonY%, ButtonY
Hotkey, %JoystickPrefix%%ButtonLb%, ButtonLb
Hotkey, %JoystickPrefix%%ButtonRb%, ButtonRb
Hotkey, %JoystickPrefix%%ButtonBk%, ButtonBk
Hotkey, %JoystickPrefix%%ButtonSt%, ButtonSt
Hotkey, %JoystickPrefix%%ButtonLs%, ButtonLs
Hotkey, %JoystickPrefix%%ButtonRs%, ButtonRs

SetTimer, WatchJoystick, 10  ; Monitor the movement of the joystick.
SetTimer, WatchMouselook, 10 ; Monitor right stick

; ~

XInput_Init()
Loop {
    Loop, 10 {
        if XInput_GetState(A_Index-1, State)=0 {
			
			SKeyToHoldDownPrev = %SKeyToHoldDown%  ; Prev now holds the key that was down before (if any).
			
			LT := json(State,"bLeftTrigger")
			RT := json(State,"bRightTrigger")

			if (LT < ThresholdLower) and (RT < ThresholdLower) {
				LTLast := false
			}
			
			if (RT < ThresholdLower) and (LTLast = false) {
				SKeyToHoldDown = 1
			}
			
            if (RT > ThresholdLower) and !(RT > ThresholdUpper)  {
					
					if (LT > ThresholdLower) and !(LT > ThresholdUpper) and (LTLast = false)  {
							SKeyToHoldDown = 6
							LTLast := true
						}
						
					if (LT > ThresholdUpper) {
							SKeyToHoldDown = 4
							LTLast := true

						}
					
					if (LT < ThresholdLower) and (LTLast = false)
						SKeyToHoldDown = 3
            }
			
			if (RT > ThresholdUpper) {
					if (LT > ThresholdUpper) {
						SKeyToHoldDown = 5
						LTLast := true
						}
						
					if (LT < ThresholdLower) and (LTLast = false)
						SKeyToHoldDown = 2					
            }
			
			if !(SKeyToHoldDownPrev = SKeyToHoldDown)
			{
				Send {LShift Down}
				Sleep 5
				Send {%SKeyToHoldDown%}						
				Sleep 5
				Send {LShift Up}						
			}
		}
    }
}
return

ButtonA:	
		if (LT < ThresholdLower) {
			Send 3
		}
		
		if (LT > ThresholdLower) and (LT < ThresholdUpper) {
			Send ^3
		}
		
		if (LT > ThresholdUpper) {
			Send {F4}
		}
return

ButtonB:	
		if (LT < ThresholdLower) {
			Send 4
		}
		
		if (LT > ThresholdLower) and (LT < ThresholdUpper) {
			Send ^4
		}
		
		if (LT > ThresholdUpper) {
			Send {F5}
		}
return

ButtonX:	
		if (LT < ThresholdLower) {
			Send 1
		}
		
		if (LT > ThresholdLower) and (LT < ThresholdUpper) {
			Send ^1
		}
		
		if (LT > ThresholdUpper) {
			Send {F2}
		}
return

ButtonY:	
		if (LT < ThresholdLower) {
			Send 2
		}
		
		if (LT > ThresholdLower) and (LT < ThresholdUpper) {
			Send ^2
		}
		
		if (LT > ThresholdUpper) {
			Send {F3}
		}
return


ButtonLb:
	if (LT < ThresholdLower) {
		Send {Click Right down}
		KeyWait 1Joy5
		Send {Click Right up} 
	}
		if (LT > ThresholdLower) {
		Send {Click Left down}
		KeyWait %JoystickPrefix%5
		Send {Click Left up} 
}
return

ButtonRb:	
		if (LT < ThresholdLower) {
			Send {Tab}
		}
		
		if (LT > ThresholdLower) and (LT < ThresholdUpper) {
			Send {Tab}
		}
		
		if (LT > ThresholdUpper) {
			Send +{Tab}
		}
return

ButtonBk:	
		if (LT < ThresholdLower) {
			Send 6
		}
		
		if (LT > ThresholdLower) and (LT < ThresholdUpper) {
			Send ^6
		}
		
		if (LT > ThresholdUpper) {
			Send ^{F1}
		}
return

ButtonSt:
		if (LT < ThresholdLower) {
			Send 5
		}
		
		if (LT > ThresholdLower) and (LT < ThresholdUpper) {
			Send ^5
		}
		
		if (LT > ThresholdUpper) {
			Send {F1}
		}
return

ButtonRs:
	if (LT < ThresholdLower) {
			Send {=}
		}
		
		if (LT > ThresholdLower) and (LT < ThresholdUpper) {
			Send ^T
		}
		
		if (LT > ThresholdUpper) {
			Send {WheelUp}
		}
return

ButtonLs:
	if (LT < ThresholdLower) {
			Send {-}
		}
		
		if (LT > ThresholdLower) and (LT < ThresholdUpper) {
			Send ^+T
		}
		
		if (LT > ThresholdUpper) {
			Send {WheelDown}
		}
return

WatchJoystick:
SetFormat, float, 03
GetKeyState, joyx, %JoystickNumber%JoyX
GetKeyState, joyy, %JoystickNumber%JoyY

XKeyToHoldDownPrev = %XKeyToHoldDown%  ; Prev now holds the key that was down before (if any).
YKeyToHoldDownPrev = %YKeyToHoldDown%  ; Prev now holds the key that was down before (if any).

if joyx > 70
    XKeyToHoldDown = e
else if joyx < 30
    XKeyToHoldDown = q
else
    XKeyToHoldDown =

if joyy > 70
    YKeyToHoldDown = s
else if joyy < 30
    YKeyToHoldDown = w
else
    YKeyToHoldDown = 
	
; Otherwise, release the previous key and press down the new key:
SetKeyDelay -1  ; Avoid delays between keystrokes.

if !(XKeyToHoldDownPrev = KeyToHoldDown)
{
  if XKeyToHoldDownPrev   ; There is a previous key to release.
   Send, {%XKeyToHoldDownPrev% up}  ; Release it.
  if XKeyToHoldDown   ; There is a key to press down.
   Send, {%XKeyToHoldDown% down}  ; Press it down.
}

if !(YKeyToHoldDownPrev = YKeyToHoldDown)
{
  if YKeyToHoldDownPrev   ; There is a previous key to release.
   Send, {%YKeyToHoldDownPrev% up}  ; Release it.
  if YKeyToHoldDown   ; There is a key to press down.
   Send, {%YKeyToHoldDown% down}  ; Press it down.
}

return

WatchMouselook:
MLMouseNeedsToBeMoved := false  ; Set default.
SetFormat, float, 03
GetKeyState, joyu, %JoystickNumber%JoyU
GetKeyState, joyr, %JoystickNumber%JoyR

ClickDownPrev = %ClickDown%  ; Prev now holds the key that was down before (if any).

if joyu > %JoyThresholdUpper%
{
    MLMouseNeedsToBeMoved := true
    DeltaU := joyu - JoyThresholdUpper
}
else if joyu < %JoyThresholdLower%
{
    MLMouseNeedsToBeMoved := true
    DeltaU := joyu - JoyThresholdLower
}
else
    DeltaU := 0

if joyr > %JoyThresholdUpper%
{
    MLMouseNeedsToBeMoved := true
    DeltaR := joyr - JoyThresholdUpper
}
else if joyr < %JoyThresholdLower%
{
    MLMouseNeedsToBeMoved := true
    DeltaR := joyr - JoyThresholdLower
}
else
    DeltaR := 0

if MLMouseNeedsToBeMoved
{
    SetMouseDelay, -1 ; Makes movement smoother.
    
    ClickDown := true
    if !(ClickDownPrev = ClickDown)
    {
      if POV_Mode = %Move_Mode%
      {
        Click down right
      }
      else if POV_Mode = %Camera_Mode%
      {
        Click down left
      }
    }

    MouseMove, DeltaU * JoyMultiplier, DeltaR * JoyMultiplier * YAxisMultiplier, 0, R
}
else
{
    ClickDown := false
    if !(ClickDownPrev = ClickDown)
    {
      if POV_Mode = %Move_Mode%
      {
        Click up right
      }
      else if POV_Mode = %Camera_Mode%
      {
        Click up left
      }
    }
}
return

